Expand description
Linux event device handling.
The Linux kernel’s “evdev” subsystem exposes input devices to userspace in a generic, consistent way. I’ll try to explain the device model as completely as possible. The upstream kernel documentation is split across two files:
- https://www.kernel.org/doc/Documentation/input/event-codes.txt
- https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt
The evdev
kernel system exposes input devices as character devices in /dev/input
,
typically /dev/input/eventX
where X
is an integer.
Userspace applications can use ioctl
system calls to interact with these devices.
Libraries such as this one abstract away the low level calls to provide a high level
interface.
Applications can interact with uinput
by writing to /dev/uinput
to create virtual
devices and send events to the virtual devices.
Virtual devices are created in /sys/devices/virtual/input
.
Devices emit events, represented by the InputEvent
type. Each device supports a few different
kinds of events, specified by the EventType
struct and the Device::supported_events()
method. Most event types also have a “subtype”, e.g. a KEY
event with a KEY_ENTER
code. This
type+subtype combo is represented by InputEventKind
/InputEvent::kind()
. The individual
subtypes of a type that a device supports can be retrieved through the Device::supported_*()
methods, e.g. Device::supported_keys()
:
use evdev::{Device, Key};
let device = Device::open("/dev/input/event0")?;
// check if the device has an ENTER key
if device.supported_keys().map_or(false, |keys| keys.contains(Key::KEY_ENTER)) {
println!("are you prepared to ENTER the world of evdev?");
} else {
println!(":(");
}
All events (even single events) are sent in batches followed by a synchronization event:
EV_SYN / SYN_REPORT / 0
.
Events are grouped into batches based on if they are related and occur simultaneously,
for example movement of a mouse triggers a movement event for the X
and Y
axes
separately in a batch of 2 events.
The evdev crate exposes functions to query the current state of a device from the kernel, as well as a function that can be called continuously to provide an iterator over update events as they arrive.
Synchronizing versus Raw modes
This library can be used in either Raw or Synchronizing modes, which correspond roughly to
evdev’s LIBEVDEV_READ_FLAG_NORMAL
and LIBEVDEV_READ_FLAG_SYNC
modes, respectively.
In both modes, calling fetch_events
and driving the resulting iterator to completion
will provide a stream of real-time events from the underlying kernel device state.
As the state changes, the kernel will write events into a ring buffer. If the buffer becomes full, the
kernel will drop events from the ring buffer and leave an event telling userspace that it
did so. At this point, if the application were using the events it received to update its
internal idea of what state the hardware device is in, it will be wrong: it is missing some
events.
In synchronous mode, this library tries to ease that pain by removing the corrupted events and injecting fake events as if the device had updated normally. Note that this is best-effort; events can never be recovered once lost. This synchronization comes at a performance cost: each set of input events read from the kernel in turn updates an internal state buffer, and events must be internally held back until the end of each frame. If this latency is unacceptable or for any reason you want to see every event directly, a raw stream reader is also provided.
As an example of how synchronization behaves, if a switch is toggled twice there will be two switch events in the buffer. However, if the kernel needs to drop events, when the device goes to synchronize state with the kernel only one (or zero, if the switch is in the same state as it was before the sync) switch events will be visible in the stream.
This cache can also be queried. For example, the DeviceState::led_vals
method will tell you which
LEDs are currently lit on the device. As calling code consumes each iterator, this state will be
updated, and it will be fully re-synchronized with the kernel if the stream drops any events.
It is recommended that you dedicate a thread to processing input events, or use epoll or an
async runtime with the fd returned by <Device as AsRawFd>::as_raw_fd
to process events when
they are ready.
For demonstrations of how to use this library in blocking, nonblocking, and async (tokio) modes, please reference the “examples” directory.
Re-exports
pub use raw_stream::AutoRepeat;
pub use raw_stream::FFEffect;
Modules
Virtual device emulation for evdev via uinput.
Structs
A wrapped input_absinfo
returned by EVIOCGABS and used with uinput to set up absolute
axes
A type of absolute axis measurement, typically used for touch events and joysticks.
A collection of bits representing either device capability or state.
A physical or virtual device supported by evdev.
A cached representation of device state at a certain time.
Event types supported by the device.
Describes a spring or friction force feedback effect.
Force feedback effect types
Describes a generic force feedback effect envelope.
Scheduling information for the force feedback effect.
Force feedback effect status
Trigger information for the force feedback effect.
An iterator over events of a Device
, produced by Device::fetch_events
.
A wrapped input_event
returned by the input device via the kernel.
Scancodes for key presses.
LEDs specified by USB HID.
Various miscellaneous event types.
Device properties.
A type of relative axis measurement, typically produced by mice.
A type associated with simple sounds, such as beeps or tones.
An event type corresponding to a physical or virtual switch.
A “synchronization” message type published by the kernel into the events stream.
A uinput event published by the kernel into the events stream for uinput devices.
A wrapped uinput_abs_setup
, used to set up analogue axes with uinput
Enums
Describes the waveform for periodic force feedback effects.
A convenience mapping from an event (type, code)
to an enumeration.
Traits
Functions
Crawls /dev/input
for evdev devices.